#pragma once
#include <iostream>
#include <unistd.h>
#include <sys/wait.h>
#include <functional>
#include "Socket.hpp"
#include "InitAddr.hpp"

// Tcp
namespace TcpServerModule
{
	using namespace SocketModule;
	using tcphandler_t = std::function<bool(Sockptr,Inetaddr)>;
	// 只负责进行IO，流式的IO，不对协议进行任何处理
	class TcpServer
	{
	public:
		TcpServer(int post) :_post(post) , _listenSocket(std::make_unique<TcpSocket>()), _running(false)
		{
		}
		void SetHandler(tcphandler_t handler)
		{
			_handler = handler;
			_listenSocket->BulidTcpserverMethod(_post);
		}
		void Loop()
		{
			_running = true;

			while (_running)
			{
				// 建立链接
				Inetaddr client_addr;
				auto sockfd = _listenSocket->SocketAccept(&client_addr);
				if (sockfd == nullptr)
					continue;
				LOG(LogLevel::DEBUG) << "get a new client, info is: " << client_addr.addr();
				pid_t pid = fork();
				if (pid == 0)
				{
					_listenSocket->SocketClose(); // 关闭监听套接字
					// 子进程
					if (fork() > 0)
						exit(0); // 父进程退出
					// 子进程变成孤儿进程
					// 处理客户端请求
					_handler(sockfd, client_addr);
					exit(0);
				}
				// 套接字关闭是网络连接正常结束的必要操作，
				// 父进程不关闭客户端套接字会打破这种正常流程，
				// 在服务器端造成连接管理混乱，
				// 在客户端（浏览器 ）则导致请求无法完整执行
				sockfd->SocketClose(); // 关闭客户端套接字
				// 父进程
				waitpid(pid, nullptr, 0);
			}

			_running = false;
		}
		~TcpServer()
		{
			_listenSocket->SocketClose();
		}

	private:
		std::unique_ptr<Socket> _listenSocket;
		bool _running;
		tcphandler_t _handler;
		int _post;
	};

}
